@using BTCPayServer.Client
@using BTCPayServer.Views.Server
@using Microsoft.AspNetCore.Mvc.TagHelpers
@using BTCPayServer.Abstractions.TagHelpers
@using BTCPayServer.Controllers
@using BTCPayServer.Views.Stores
@model UpdateRoleViewModel
@{
    var role = Context.GetRouteValue("role") as string;

    if (role == "create")
        role = null;

    var storeId = Context.GetRouteValue("storeId") as string;
    var title = role is null ? StringLocalizer["Create role"] : StringLocalizer["Update Role"];
    var category = storeId is null ? WellKnownCategories.Server : WellKnownCategories.Store;
    ViewData.SetLayoutModel(new LayoutModel(nameof(StoreNavPages.Roles), title).SetCategory(category));
    var storePolicies = Policies.AllPolicies.Where(Policies.IsStorePolicy).ToArray();
}

<form method="post">
    <div class="sticky-header">
        <nav aria-label="breadcrumb">
            <ol class="breadcrumb">
                <li class="breadcrumb-item">
                    <a asp-action="ListRoles" asp-route-storeId="@storeId">Roles</a>
                </li>
                <li class="breadcrumb-item active" aria-current="page">@ViewData["Title"]</li>
            </ol>
            <h2>@ViewData["Title"]</h2>
        </nav>
        <button id="page-primary" type="submit" class="btn btn-primary" name="command" value="Save">Save</button>
    </div>

    <div class="row">
        <div class="col-xxl-constrain">
            @if (!ViewContext.ModelState.IsValid)
            {
                <div asp-validation-summary="ModelOnly"></div>
            }
            <div class="form-group" style="max-width:320px">
                <label asp-for="Role" class="form-label"></label>
                @if (role == null)
                {
                    <input asp-for="Role" required="required" class="form-control" />
                }
                else
                {
                    <input type="hidden" asp-for="Role" />
                    <input required="required" class="form-control" disabled value="@Model.Role" />
                }
                <span asp-validation-for="Role" class="text-danger"></span>
            </div>

            <h4 class="mt-4 mb-3">Permissions</h4>
            <select multiple="multiple" asp-for="Policies" class="form-select hide-when-js">
                @foreach (var policy in storePolicies)
                {
                    <option value="@policy" class="text-truncate" asp-selected="@(Model.Policies?.Contains(policy) ?? false)">@policy</option>
                }
            </select>
            <div class="list-group mb-2">
                @{
                    var storePolicyMap = Permission.PolicyMap.Where(pair => Policies.IsStorePolicy(pair.Key)).ToArray();
                    var topMostPolicies = storePolicyMap.Where(pair => !storePolicyMap.Any(valuePair => valuePair.Value.Contains(pair.Key)));
                    @foreach (var policy in topMostPolicies)
                    {
                        RenderTree(policy, storePolicyMap, Model.Policies.Contains(policy.Key));
                    }
                }
            </div>
            <span asp-validation-for="Policies" class="text-danger"></span>
        </div>
    </div>
</form>

@{
    void RenderTree(KeyValuePair<string, HashSet<string>> policy, KeyValuePair<string, HashSet<string>>[] storePolicyMap, bool isChecked)
    {
        <div class="form-check mb-0">
            <input type="checkbox" class="form-check-input policy-cb" checked="@isChecked" value="@policy.Key" id="Policy-@policy.Key.Replace(".", "_")" />
            <label class="h5 fw-semibold form-check-label mb-1" for="Policy-@policy.Key.Replace(".", "_")" data-bs-toggle="tooltip" title="@policy.Key">
                @UIManageController.AddApiKeyViewModel.PermissionValueItem.PermissionDescriptions[policy.Key].Title
            </label>
            <p class="text-muted">@UIManageController.AddApiKeyViewModel.PermissionValueItem.PermissionDescriptions[policy.Key].Description</p>
            @if (policy.Value?.Any() is true)
            {
                <div class="list-group">
                    @foreach (var subPolicy in policy.Value)
                    {
                        var match = storePolicyMap.SingleOrDefault(pair => pair.Key == subPolicy);
                        RenderTree(match.Key is not null ? match : new KeyValuePair<string, HashSet<string>>(subPolicy, null), storePolicyMap, !isChecked && Model.Policies.Contains(subPolicy));
                    }
                </div>
            }
        </div>
    }
}
<script>
    function handleCheckboxChange(element) {
        const { checked, value: policy } = element;
        const policySelect = document.getElementById('Policies');
        const subPolicies = element.parentElement.querySelectorAll(`.list-group .policy-cb:not([value="${policy}"])`);

        policySelect.querySelector(`option[value="${policy}"]`).selected = checked;
        subPolicies.forEach(subPolicy => {
            subPolicy.checked = checked? false : subPolicy.checked;
            if (checked){
                subPolicy.setAttribute("disabled", "disabled");
            } else {
                subPolicy.removeAttribute("disabled");
            }
            policySelect.querySelector(`option[value="${subPolicy.value}"]`).selected = subPolicy.checked;
        });
    }

    document.addEventListener('DOMContentLoaded', () => {
        document.querySelectorAll(".policy-cb:checked").forEach(handleCheckboxChange);

        delegate('change', '.policy-cb', event => {
           handleCheckboxChange(event.target);
        });
    });
</script>
